package io.jpress.module.article.flowable.listener;

import com.jfinal.aop.Inject;
import io.jpress.commons.flowable.FlowConsts;
import io.jpress.core.flowable.AutoLoadEventListener;
import io.jpress.core.flowable.FlowableUtil;
import io.jpress.model.User;
import io.jpress.module.article.flowable.ArticleFlowConsts;
import io.jpress.module.article.model.ArticleFlowStatus;
import io.jpress.module.article.service.ArticleFlowStatusService;
import io.jpress.service.DepartmentService;
import io.jpress.service.UserService;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 任务被创建（这里可能是用户任务，也可能是系统任务）主要作用：
 * 1、设置 assigneeList 参数，若其配置了部门的话
 * 2、若当前任务回到了发布人的手里，需要设置文章为可编辑状态
 */
@AutoLoadEventListener(types = FlowableEngineEventType.TASK_CREATED)
public class ArticleTaskCreateListener implements FlowableEventListener {

    @Inject
    private DepartmentService departmentService;

    @Inject
    private UserService userService;

    @Inject
    private ArticleFlowStatusService articleFlowStatusService;

    @Override
    public void onEvent(FlowableEvent event) {

        if (!(event instanceof FlowableEntityEventImpl)) {
            return;
        }


        FlowableEntityEventImpl e = (FlowableEntityEventImpl) event;
        if (!(e.getEntity() instanceof TaskEntityImpl)) {
            return;
        }

        TaskEntityImpl entity = (TaskEntityImpl) e.getEntity();

        //非文章类的流程
        if (!ArticleFlowConsts.ARTICLE_CONTENT_TYPE.equals(entity.getVariable(FlowConsts.VAR_CONTENT_TYPE))) {
            return;
        }

        FlowElement flowElement = FlowableUtil.getFlowElementByDefKey(entity.getProcessDefinitionId(), entity.getTaskDefinitionKey());

        //用户任务
        if (flowElement instanceof UserTask) {

            //设置 assigneeList 参数
            setAssigeeListVariable(entity, (UserTask) flowElement);

            //设置流程状态
            setArticleFlowStatus(entity);
        }

    }


    /**
     * 如果流程回到的作者，并且需要修改文章，则让文章的流程状态为可以修改
     *
     * @param entity
     */
    private void setArticleFlowStatus(TaskEntityImpl entity) {
        if (FlowConsts.ACTION_STATUS_REBUT.equals(entity.getVariable(FlowConsts.VAR_ACTION))) {

            Long authorId = (Long) entity.getVariable(ArticleFlowConsts.VAR_AUTHOR_ID);

            //文章作者自己的任务
            if (authorId != null && authorId.toString().equals(entity.getAssignee())) {
                ArticleFlowStatus flowStatus = articleFlowStatusService.findByProcessInstanceId(entity.getProcessInstanceId());
                if (flowStatus != null && !flowStatus.isFinished()) {
                    flowStatus.setStatus(ArticleFlowStatus.STATUS_REBUT);
                    articleFlowStatusService.update(flowStatus);
                }
            }
        }
    }


    /**
     * 设置 assigneeList 参数
     *
     * @param entity
     * @param flowElement
     */
    private void setAssigeeListVariable(TaskEntityImpl entity, UserTask flowElement) {
        UserTask userTask = flowElement;
        List<String> groups = userTask.getCandidateGroups();
        entity.removeVariable("assigneeList");

        if (groups != null && !groups.isEmpty()) {
            Set<Long> assigneeList = new HashSet<>();
            for (String group : groups) {
                List<User> users = userService.findListByDepartmentId(Long.valueOf(group));
                if (users != null) {
                    users.forEach(user -> assigneeList.add(user.getId()));
                }
            }
            if (!assigneeList.isEmpty()) {
                entity.setVariable("assigneeList", assigneeList);
            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }
}
